﻿namespace System.Dynamic
{
	/// <summary>
	/// Contains the main operators for building dynamic objects.
	/// </summary>
	public static partial class Dynamics
	{
		/// <summary>
		/// Creates a snapshot of all property values of an object.
		/// </summary>
		/// <param name="obj">The object to create a snapshot of.</param>
		/// <returns>Returns a snapshot of the object.</returns>
		/// <remarks>This operator is not intended to use with primitive types.</remarks>
		/// <example>
		/// Counter counter = new Counter();
		/// counter.Value++;
		/// 
		/// // create a snapshot of counter
		/// dynamic snapshot = Dynamics.Snapshot(counter);
		/// 
		/// // change the counter
		/// counter.Value++;
		/// 
		/// // snapshot still shows the old value
		/// Console.WriteLine(snapshot.Value);
		/// </example>
		public static dynamic Snapshot(object obj)
		{
			return new ObjectSnapshot(obj);
		}

		/// <summary>
		/// Wraps an object into a dynamic proxy.
		/// </summary>
		/// <param name="obj">The object to wrap.</param>
		/// <returns>Returns the specified object as a dynamic one.</returns>
		public static dynamic Proxy(object obj)
		{
			return obj;
		}

		/// <summary>
		/// Combines multiple objects into a single one.
		/// </summary>
		/// <param name="objects">The objects to combine.</param>
		/// <returns>The combined objects.</returns>
		/// <remarks></remarks>
		/// <example>
		/// public class C1
		/// {
		///		public int A { get; set; }
		///	}
		/// public class C2
		/// {
		///		public int B { get; set; }
		///	}
		///	
		/// dynamic m = Dynamics.Combine(new C1 { A = 1 }, new C2 { B = 2 });
		/// Console.WriteLine(m.A);
		/// Console.WriteLine(m.B);
		/// </example>
		public static dynamic Combine(params object[] objects)
		{
			return new CombinedObject(objects);
		}

		/// <summary>
		/// Handles multiple objects as one, performs every operation on each object.
		/// </summary>
		/// <param name="objects">The target objects.</param>
		/// <returns>Returns a proxy that replicates every operation on each object contained in the collection.</returns>
		/// <remarks></remarks>
		/// <example>
		/// dynamic allAsOne = Dynamics.Multicast(recipients);
		/// allAsOne.Say("Hello");
		/// </example>
		public static dynamic Multicast(params object[] objects)
		{
			return new MulticastObject(objects);
		}

		/// <summary>
		/// Distributes operations across multiple objects of the same kind.
		/// </summary>
		/// <typeparam name="T">The type of the target objects.</typeparam>
		/// <param name="objects">The target objects that provide the same service.</param>
		/// <returns></returns>
		/// <remarks>The load balancer uses the Round-robin method to distribute operations.</remarks>
		/// <example>
		/// IService s1, s2;
		/// 
		/// dynamic lb = Dynamics.LoadBalance&lt;IService&gt;(s1, s2);
		/// lb.DoWork(1);
		/// lb.DoWork(2);
		/// </example>
		public static dynamic LoadBalance<T>(params T[] objects)
		{
			return new LoadBalancerObject<T>(objects);
		}
	}
}
